<template>
	<view class="uv-drop-down-popup">
		<uv-transition :show="show" mode="fade" :duration="300" :custom-style="overlayStyle" @click="clickOverlay">
			<view class="uv-dp__container" ref="uvDPContainer" :style="{ height: `${height}px` }" @click.stop="blockClick">
				<view class="uv-dp__container__list" ref="uvDPList">
					<slot>
						<view class="uv-dp__container__list--item" v-for="(item, index) in list" :key="index" @click="clickHandler(item, index)" :style="[itemCustomStyle(index)]">
							<uv-text :text="item[keyName]" :size="getTextSize(index)" :color="getTextColor(index)"></uv-text>
						</view>
					</slot>
				</view>
			</view>
		</uv-transition>
	</view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js';
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js';
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
const dom = uni.requireNativePlugin('dom');
// #endif
/**
 * DropDownPopup 下拉框
 * @description 下拉筛选框
 * @tutorial https://ext.dcloud.net.cn/plugin?name=uv-drop-down
 * @property {String | Number} name 字段标识
 * @property {String | Number} zIndex 弹出层的层级
 * @property {String | Number} opacity 遮罩层的透明度
 * @property {Boolean} clickOverlayOnClose 是否允许点击遮罩层关闭弹窗
 * @property {Object} currentDropItem 当前下拉筛选菜单对象
 * @property {String} keyName 指定从当前下拉筛选菜单对象元素中读取哪个属性作为文本展示
 */
export default {
	name: 'uv-drop-down-popup',
	mixins: [mpMixin, mixin],
	props: {
		sign: {
			type: [String, Number],
			default: 'UVDROPDOWN'
		},
		zIndex: {
			type: [Number, String],
			default: 999
		},
		opacity: {
			type: [Number, String],
			default: 0.5
		},
		clickOverlayOnClose: {
			type: Boolean,
			default: true
		},
		// 当前下拉选项对象
		currentDropItem: {
			type: Object,
			default() {
				return {
					activeIndex: 0,
					child: []
				};
			}
		},
		keyName: {
			type: String,
			default: 'label'
		},
		// ztab 的高度
		zTabHeigth: {
			type: Number,
			default: 0
		}
	},
	data() {
		return {
			show: false,
			rect: {},
			height: 0
		};
	},
	computed: {
		overlayStyle() {
			let { height = 0, top = 0 } = this.rect;
			// #ifdef H5
			top += this.$uv.sys().windowTop;
			// #endif
			// console.log('top ===> ', top);
			const style = {
				position: 'fixed',
				top: `${top + height - this.zTabHeigth}px`,
				left: 0,
				right: 0,
				zIndex: this.zIndex,
				bottom: 0,
				'background-color': `rgba(0, 0, 0, ${this.opacity})`
			};
			return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle));
		},
		list() {
			try {
				return Array.isArray(this.currentDropItem.child) ? this.currentDropItem.child : [];
			} catch (e) {
				return [];
			}
		},
		getTextColor(index) {
			return (index) => {
				const active = this.currentDropItem.activeIndex == index;
				const color = this.currentDropItem.color;
				const activeColor = this.currentDropItem.activeColor;
				if (active) {
					return activeColor ? activeColor : '#3c9cff';
				}
				return color ? color : '#333';
			};
		},
		getTextSize(index) {
			return (index) => {
				const active = this.currentDropItem.activeIndex == index;
				const size = this.currentDropItem.size;
				const activeSize = this.currentDropItem.activeSize;
				if (active) {
					return activeSize ? activeSize : '30rpx';
				}
				return size ? size : '30rpx';
			};
		},
		itemCustomStyle() {
			return (index) => {
				const active = this.currentDropItem.activeIndex == index;
				const style = {};
				if (active && this.currentDropItem.itemActiveCustomStyle) {
					return this.$uv.deepMerge(style, this.$uv.addStyle(this.currentDropItem.itemActiveCustomStyle));
				}
				if (this.currentDropItem.itemCustomStyle) {
					return this.$uv.deepMerge(style, this.$uv.addStyle(this.currentDropItem.itemCustomStyle));
				}
				return style;
			};
		}
	},
	created() {
		this.init();
	},
	methods: {
		blockClick() {},
		clickHandler(item, index) {
			this.currentDropItem.activeIndex = index;
			this.$emit('clickItem', item);
			this.close();
		},
		init() {
			uni.$off(`${this.sign}_GETRECT`);
			uni.$on(`${this.sign}_GETRECT`, (rect) => {
				this.rect = rect;
			});
			uni.$off(`${this.sign}_CLICKMENU`);
			uni.$on(`${this.sign}_CLICKMENU`, async (res) => {
				if (res.show) {
					this.open();
				} else {
					this.close();
				}
			});
		},
		open() {
			this.show = true;
			this.$nextTick(async () => {
				// #ifndef H5 || MP-WEIXIN
				await this.$uv.sleep(60);
				// #endif
				const res = await this.queryRect();
				// #ifndef APP-NVUE
				this.height = res.height;
				// #endif
				// #ifdef APP-NVUE
				this.animation(res.height);
				// #endif
				this.$emit('popupChange', { show: true });
			});
		},
		close() {
			if (!this.show) return;
			this.height = 0;
			// #ifndef APP-NVUE
			this.height = 0;
			// #endif
			// #ifdef APP-NVUE
			this.animation(0);
			// #endif
			this.show = false;
			uni.$emit(`${this.sign}_CLOSEPOPUP`);
			this.$emit('popupChange', { show: false });
		},
		clickOverlay() {
			if (this.clickOverlayOnClose) {
				this.close();
			}
		},
		// 查询内容高度
		queryRect() {
			// #ifndef APP-NVUE
			// 组件内部一般用this.$uvGetRect，对外的为getRect，二者功能一致，名称不同
			return new Promise((resolve) => {
				this.$uvGetRect(`.uv-dp__container__list`).then((size) => {
					resolve(size);
				});
			});
			// #endif
			// #ifdef APP-NVUE
			// nvue下，使用dom模块查询元素高度
			// 返回一个promise，让调用此方法的主体能使用then回调
			return new Promise((resolve) => {
				dom.getComponentRect(this.$refs.uvDPList, (res) => {
					resolve(res.size);
				});
			});
			// #endif
		},
		// nvue下设置高度
		animation(height, duration = 200) {
			// #ifdef APP-NVUE
			const ref = this.$refs['uvDPContainer'];
			animation.transition(ref, {
				styles: {
					height: `${height}px`
				},
				duration
			});
			// #endif
		}
	}
};
</script>
<style scoped lang="scss">
.uv-dp__container {
	/* #ifndef APP-NVUE */
	overflow: hidden;
	transition: all 0.15s;
	/* #endif */
	background-color: #fff;
}
.uv-dp__container__list {
	&--item {
		padding: 20rpx 60rpx;
	}
}
</style>
